<?php

/**
 * Created by PhpStorm.
 * User: deyanliu
 * Company: YiDuYongChe
 * Date: 16/6/14
 * Time: 上午11:41
 */
namespace common\components;

use common\constants\Constants;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use Yii;
use yii\base\Component;

/**
 * @inheritdoc
 *
 * @property \app\models\User|\yii\web\IdentityInterface|null $identity The identity object associated with the currently logged-in user. null is returned if the user is not logged in (not authenticated).
 */
class Utils extends Component {
	public $redis;
	const SMS = 0;
	const PUSH = 1;
	const NUM = 0;
	const STR = 1;

	const STATUS_SUCCESS = 0;
	const STATUS_FAILED = 1;
	const BAIDU_API_KEY = 'c89078e1bbe43c14eb373f7344b206ea'; //apikey 这个目前是测试的zhangbingshuai

	public function init() {
		//$this->redis = \Yii::$app->redis;
	}

	/**
		     * 检查手机号码是否合法, 返回值 true/false
	*/
	public function checkMobile($mobile) {
		if (preg_match("/^1[34578]{1}\d{9}$/", $mobile)) {
			return true;
		} else {
			return false;
		}
	}

	/*
		     * 检查邮箱是否合法, 返回值 true/false
	*/
	public function checkEmail($email) {
		if (preg_match("/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/", $email)) {
			return true;
		} else {
			return false;
		}
	}

	public function getRandStr($length,$type = 1 ) {
		// 密码字符集，可任意添加你需要的字符
		if ($type == self::NUM) {
			$chars = '1234567890';
		} else {
			$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxzy23456789';
		}

		$randstr = '';
		for ($i = 0; $i < $length; $i++) {
			// 这里提供两种字符获取方式
			// 第一种是使用 substr 截取$chars中的任意一位字符；
			// 第二种是取字符数组 $chars 的任意元素
			// $randstr .= substr($chars, mt_rand(0, strlen($chars) – 1), 1);
			$randstr .= $chars[mt_rand(0, strlen($chars) - 1)];
		}
		return $randstr;
	}

	public function GetSMSContentByTemplateId($template_id, $content_array) {
		$content = json_encode($content_array);
		return "$template_id $content";
	}

	/*
		     * 发送验证码短信
	*/
	public function sendCodeSMS($mobile, $code) {
		$template_id = \Yii::$app->params['CHECK_CODE'];
		$content_array = array('code' => $code);
		$ret = $this->sendSMS($mobile, $template_id, $content_array);
		return $ret;
	}

	/*
		     * 功能: 2016 10 27 百川迁移至大于 , 注意 $content_array 中都应是 string类型,不能使用int型,不然发送失败
		     * @param :$multiple 是否发送多个电话号码,多个的话就不做验证
	*/
	public function sendSMS($mobile, $template_id, $content_array, $multiple = 0) {
		if ($multiple == 0) {
			$is_mobile = $this->checkMobile($mobile);
		} else {
			$is_mobile = 1;
		}

		if ($is_mobile) {
			$content = $this->GetSMSContentByTemplateId($template_id, $content_array);

			$redis_array = array(
				"cmd" => self::SMS,
				"mobile" => $mobile,
				"content" => $content,
				"template_id" => $template_id,
				"content_array" => json_encode($content_array),
				"is_mobile" => $is_mobile,
			);

			$ret = $this->redis->executeCommand('PUBLISH', ["queue", json_encode($redis_array)]);
			//添加成功返回值为1
			if ($ret == 1) {
				$result = true;
			} else {
				$result = false;
			}

		} else {
			$result = false;
		}

		return $result;

	}

	public function hidePhoneNum($phone) {
		if (is_null($phone)) {
			return null;
		}
		if (strlen($phone) > 7) {
			return substr_replace($phone, '****', 3, 4);
		}
		return $phone;
	}

	public function getSqlArrayStr($array) {
		if (empty($array)) {
			return null;
		}
		$str = '(';
		foreach ($array as $value) {
			$str = $str . $value . ',';
		}
		$str = rtrim($str, ',');
		return $str . ')';
	}

	public function getBaseHolidayPer() {
		$today = date('Y-m-d');
		$flag = 0;

		$sql = "SELECT cfg_value from 630_config where cfg_name =:holiday_date";
		$command = \Yii::$app->db->createCommand($sql);
		$command->bindValue(':holiday_date', 'holiday_date');
		$ret_arr = $command->queryAll();
		$date_str = $ret_arr[0]['cfg_value'];

		$date_arr = explode(',', $date_str);
		foreach ($date_arr as $date) {
			if ($today == $date) {
				$flag = 1;
			}
		}
		return $flag;
	}

	/*
		     * 函数功能 : 发送邮件的
		     * $ToUser    收件人
		     * $Subject   邮件主题 , eg : '密码找回' ..
		     * $Contents  邮件内容 , 支持 html 结构文件
	*/
	public function sendMails($ToUser, $Subject, $Contents) {
		$mail = Yii::$app->mailer->compose();
		$mail->setTo($ToUser);
		$mail->setSubject($Subject);
		$mail->setHtmlBody($Contents); //发布可以带html标签的文本
		if ($mail->send()) {
			return true;
		} else {
			return false;
		}
	}

	/**
   * 函数功能 : 发送邮件的
   * $ToUser    收件人
   * $Subject   邮件主题 , eg : '密码找回' ..
   * $Contents  邮件内容 , 支持 html 结构文件
  */
	public function sendMailsBy400($ToUser, $Subject, $Contents) {
		$mail = Yii::$app->mailer400->compose();
		$mail->setTo($ToUser);
		$mail->setSubject($Subject);
		$mail->setHtmlBody($Contents); //发布可以带html标签的文本
		if ($mail->send()) {
			return true;
		} else {
			return false;
		}
	}

	public function getBaiduDist($lat1, $lng1, $lat2, $lng2, $origin_region = "北京", $dest_region = "北京") {
		$ak = Constants::BAIDU_DIST_AK;
		$uri = Constants::BIADU_DIST_URI;
		$distance = 0;
		if ($lat1 > 0 && $lat2 > 0 && $lng1 > 0 && $lng2 > 0) {
			$origin = "$lat1,$lng1";
			$dest = "$lat2,$lng2";
			$originregion = $origin_region;
			$dest_region = $dest_region;
			$url = "http://api.map.baidu.com/direction/v1?mode=driving&origin=$origin&destination=$dest&origin_region=$origin_region&destination_region=$dest_region&output=json&ak=$ak";

			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			$head = curl_exec($ch);
			curl_close($ch);
			//api_log( basename(__FILE__) . ", get_baidu_dist(), $lat1, $lng1, $lat2, $lng2, $origin_region, $dest_region" );

			if ($head == false) {
				$distance = 0;
			} else {
				$output = json_decode($head);
				$result = $output->result;
				$routes = $result->routes;
				$distance = $routes[0]->distance;
			}
			$output_debug = json_encode($output);
			//api_log( basename(__FILE__) . ", get_baidu_dist(), $output_debug" );

		}
		//$distance = floor( $distance / 1000 );
		$distance = floor($distance);
		//api_log( basename(__FILE__) . ", get_baidu_dist(), distance: $distance" );
		return $distance;

	}

	/**
	 * 执行成功，组装应答数据
	 * @param array $data 数据
	 * @param string $msg 提示信息
	 * @param int $status 状态码
	 * @return array
	 */
	public function getSuccessArray($data = [], $msg = '', $status = self::STATUS_SUCCESS) {
		return $this->getResultArray($status, $msg, $data);
	}

	/**
	 * 执行失败，组装应答数据
	 * @param string $msg 提示信息
	 * @param int $status 状态码
	 * @param array $data 数据
	 * @return array
	 */
	public function getFailedArray($msg = '', $status = self::STATUS_FAILED, $data = []) {
		return $this->getResultArray($status, $msg, $data);
	}

	/**
	 * 组装应答数据
	 * @param $status
	 * @param $msg
	 * @param $data
	 * @return array
	 */
	public function getResultArray($status, $msg, $data) {
		return ['status' => $status, 'msg' => $msg, 'data' => $data];
	}

	/**
	 * gps 转换为 百度地图
	 * 经度 , 纬度
	 * (lng经度)  ,  (lat纬度)
	 * return  返回 经度纬度
	 */
	public function gps_to_baidu($coords) {

		$uri = "http://api.map.baidu.com/geoconv/v1/?";
		$ak = "II2IyDmCGxmVCKaGQTigMkFK";
		//global $uri, $ak;
		$url = $uri . "coords=" . $coords . "&from=1&to=5&ak=" . $ak;

		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		$head = curl_exec($ch);
		//$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);

		$output = json_decode($head);
		$result = $output->result;
		$ret = $result[0];

		//$ret_coords = $ret->y . "," . $ret->x;
		//return $ret_coords;
		if ($ret) {
			return array($ret->x, $ret->y);
		}

	}

	/**
	 * 得到当前登录用户的uid
	 * (在控制器中可以调用$this->userId 获得uid,假如在模型中使用uid,又没有传递uid,可通过此方法调用)
	 * @param string $msg 提示信息
	 * @param int $status 状态码
	 * @param array $data 数据
	 * @return int or null
	 */
	public function getUid() {
		$session = \Yii::$app->session;
		$uid = $session->get(\frontend\models\Login::SESSION_KEY_USER_ID);
		return $uid;
	}

	/**
	 * 获得session中指定的字段值
	 */
	public function getsession_admin_id($id) {
		$session = Yii::$app->session;
		$userInfo = $session->get('userInfo');
		return $userInfo[$id];
	}

	/**
	 * 导出Excel
	 */
	public function getExcel($fileName, $headArr, $data, $roo) {
		//对数据进行检验
		if (empty($data) || !is_array($data)) {
			die("data must be a array");
		}
		//检查文件名
		if (empty($fileName)) {
			exit;
		}

		$date = date("Y_m_d", time());
		$fileName .= "_{$date}.xls";

		//创建PHPExcel对象，注意，不能少了\
		$objPHPExcel = new \PHPExcel();
		$objProps = $objPHPExcel->getProperties();

		//设置表头
		$key = ord("A");
		foreach ($headArr as $v) {
			$colum = chr($key);
			$objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
			$key += 1;
		}

		$column = 2;
		$objActSheet = $objPHPExcel->getActiveSheet();

		//设置为文本格式
		foreach ($data as $key => $rows) {
			//行写入
			$span = ord("A");
			foreach ($roo as $v) {
				$j = chr($span);
				if (isset($rows[$v])) {
					$objActSheet->setCellValueExplicit($j . $column, $rows[$v]);
				}
				$span++;
			}
			$column++;
		}

		$fileName = iconv("utf-8", "gb2312", $fileName);
		//重命名表
		// $objPHPExcel->getActiveSheet()->setTitle('test');
		//设置活动单指数到第一个表,所以Excel打开这是第一个表
		$objPHPExcel->setActiveSheetIndex(0);
		ob_end_clean(); //清除缓冲区,避免乱码
		header('Content-Type: application/vnd.ms-excel');
		header("Content-Disposition: attachment;filename=\"$fileName\"");
		header('Cache-Control: max-age=0');

		$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
		$objWriter->save('php://output'); //文件通过浏览器下载
		exit;
	}

	/**
	 * 得到host
	 */
	public function getHostName() {
		$host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
		return $host;
	}

	/**
	 * 功能:双向加解密的函数
	 * @param $string 要加密的字符
	 * @parm  $operation  ENCODE 加密  ; DECODE 解密
	 * @parm  $key  加密时使用的key
	 * @parm  $ckey_length =0则相同字符加密后唯一 ; !=0则加密后不同
	 * @parm  $expiry  过期时间(秒)
	 * @return 加密39位string ; 解密对应的字符
	 */
	function authcode($string, $operation = 'DECODE', $key = '', $ckey_length = 4, $expiry = 0) {
		// 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
		// 密匙
		$key = md5($key ? $key : 'xxx');
		// 密匙a会参与加解密
		$keya = md5(substr($key, 0, 16));
		// 密匙b会用来做数据完整性验证
		$keyb = md5(substr($key, 16, 16));
		// 密匙c用于变化生成的密文
		$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
		// 参与运算的密匙
		$cryptkey = $keya . md5($keya . $keyc);
		$key_length = strlen($cryptkey);
		// 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，
		//解密时会通过这个密匙验证数据完整性
		// 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
		$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) :
		sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
		$string_length = strlen($string);
		$result = '';
		$box = range(0, 255);
		$rndkey = array();
		// 产生密匙簿
		for ($i = 0; $i <= 255; $i++) {
			$rndkey[$i] = ord($cryptkey[$i % $key_length]);
		}
		// 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
		for ($j = $i = 0; $i < 256; $i++) {
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}
		// 核心加解密部分
		for ($a = $j = $i = 0; $i < $string_length; $i++) {
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			// 从密匙簿得出密匙进行异或，再转成字符
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}
		if ($operation == 'DECODE') {
			// 验证数据有效性，请看未加密明文的格式
			if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
				substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)
			) {
				return substr($result, 26);
			} else {
				return '';
			}
		} else {
			// 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
			// 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
			return $keyc . str_replace('=', '', base64_encode($result));
		}
	}

	/**
	 * 功能:中奖率
	 * @param : $num是中奖概率 0-100
	 */
	function property($num) {
		if (is_numeric($num) && $num >= 0 && $num <= 100) {
			$randNum = rand(0, 100);
			if ($randNum <= $num) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 功能：通过ip定位城市信息
	 * ip自动识别当前请求的ip
	 * 参考:http://apistore.baidu.com/apiworks/servicedetail/114.html
	 */
	function getPositionByIp($ip) {
		$ch = curl_init();
		$apikey = self::BAIDU_API_KEY;
		$url = "http://apis.baidu.com/apistore/iplookupservice/iplookup?ip=$ip";
		$header = array(
			"apikey: $apikey",
		);
		// 添加apikey到header
		curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		// 执行HTTP请求
		curl_setopt($ch, CURLOPT_URL, $url);
		$res = curl_exec($ch);
		return $res;
	}

	/**
	 * 记录日志
	 */
	function apiLog($log, $module = 'h5') {
		$route = Yii::$app->requestedRoute;
		$log_filename = $module.'_' . date("Y-m-d") . ".log";
		$pid = getmypid();
		$log_path = Yii::$app->params['log_path'];
		$file = $log_path . $log_filename;
		file_put_contents($file, date("Y-m-d H:i:s ") . "pid: $pid " . "router = " . $route . '  ' . $log . "\n", FILE_APPEND);
	}

	/**
	 * http Post请求
	 * @param $url
	 * @param array $data
	 * @return mixed
	 */
	function httpPost($url, $data = []) {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		// 设置请求为post类型
		curl_setopt($ch, CURLOPT_POST, 1);
		// 添加post数据到请求中
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

		// 执行post请求，获得回复
		$response = curl_exec($ch);
		curl_close($ch);
		return $response;
	}

	/**
     * 功能:给安卓,ios push消息
     * $msg_body 格式: $mq_msg_array = array( "type" => 2, "userid" => $uid, "ticker" => $ticker, "title" => $title, "msg" => $msg); $mq_msg_json = json_encode($mq_msg_array);
	*/
	function pushAndroidAndIos($msg_body, $exchange = "router", $queue = "msgs") {
		$exchange = $exchange;
		$queue = $queue;
		$host = \Yii::$app->params['push_rabbitmq']['host'];
		$port = \Yii::$app->params['push_rabbitmq']['port'];
		$user = \Yii::$app->params['push_rabbitmq']['user'];
		$password = \Yii::$app->params['push_rabbitmq']['password'];
		$vhost = \Yii::$app->params['push_rabbitmq']['vhost'];
		$conn = new AMQPStreamConnection($host, $port, $user, $password, $vhost);
		$ch = $conn->channel();

		/*
			            The following code is the same both in the consumer and the producer.
			            In this way we are sure we always have a queue to consume from and an
			                exchange where to publish messages.
		*/

		/*
			            name: $queue
			            passive: false
			            durable: true // the queue will survive server restarts
			            exclusive: false // the queue can be accessed in other channels
			            auto_delete: false //the queue won't be deleted once the channel is closed.
		*/
		$ch->queue_declare($queue, false, true, false, false);

		/*
			            name: $exchange
			            type: direct
			            passive: false
			            durable: true // the exchange will survive server restarts
			            auto_delete: false //the exchange won't be deleted once the channel is closed.
		*/

		$ch->exchange_declare($exchange, 'direct', false, true, false);

		$ch->queue_bind($queue, $exchange);

		//$msg_body = implode(' ', array_slice($argv, 1));
		$msg = new AMQPMessage($msg_body, array('content_type' => 'text/plain', 'delivery_mode' => 2));
		$ch->basic_publish($msg, $exchange);

		$ch->close();
		$conn->close();
	}

	/**
	 * 通过百度API获取经纬度地址详情
	 * @param  [type] $lat [description]
	 * @param  [type] $lng [description]
	 * @return [type]      [description]
	 */
	function getAddressDetailsFromBaidu($lat, $lng) {
		$uri = "http://api.map.baidu.com/geocoder/v2/?";
		$ak = "II2IyDmCGxmVCKaGQTigMkFK";
		//global $uri, $ak;
		$url = $uri . "location=" . $lat . ',' . $lng . "&output=json&ak=" . $ak;

		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		$head = curl_exec($ch);
		//$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);
		$output = json_decode($head, true);
		return $output;
	}

	/**
   * 功能:获得版本号码
   * @param 版本号clientversion  android_2703
	*/
	function getClientVersion($clientversion) {
		if (strlen($clientversion) == 0) {
			$this->apiLog(basename(__FILE__) . 'get_client_version(), clientversion is null.', $module = '');
		}
		$version_arr = explode('_', $clientversion);
		if (count($version_arr) > 1) {
			return array('os' => $version_arr[0], 'version' => $version_arr[1]);
		} else {
			$this->apiLog(basename(__FILE__) . 'get_client_version(), version_arr is null.', $module = '');
		}
		return array('os' => '', 'version' => '');
	}
	/**
	 * http Get请求
	 * @param $url
	 * @param array $data
	 * @return mixed
	 */
	function httpGet($url, $data = [])
	{
		if(!empty($data)){
			$paramStr = http_build_query($data);
			$url = $url."?".$paramStr;
		}
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_HEADER, 0);

		// 执行get请求，获得回复
		$response = curl_exec($ch);
		curl_close($ch);
		return $response;
	}

	/**
	 * 获取当前毫秒数
	 * @return [type] [description]
	 */
	function getMicrotime($utimestamp = null){
			if (is_null($utimestamp)){
					$utimestamp = microtime(true);
			}
			list($msec, $sec) = explode(' ', microtime());
			$msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
			return $msectime;
	}

}
